<template>
  <el-breadcrumb class="app-breadcrumb breadcrumb-container"
                 separator="/">
    <el-breadcrumb-item v-for="(item,index) in levelList"
                        :key="item.path">
      <!-- 面包屑导航最后一个是不可点击的 因为最后一个正是当前所显示的路由 -->
      <span v-if="index==levelList.length-1"
            class="no-redirect">{{item.meta.title}}</span>
      <a v-else
         @click.prevent="handleLink(item)">{{item.meta.title}}</a>
    </el-breadcrumb-item>
  </el-breadcrumb>
</template>

<script lang="ts">
import {
  RouteLocationMatched,
  RouteLocationRaw,
  useRoute,
  useRouter
} from 'vue-router'
import { defineComponent, onBeforeMount, ref, watch } from 'vue'
import { compile } from 'path-to-regexp'

type PartialRouteLocationMatched = Partial<RouteLocationMatched>

export default defineComponent({
  name: 'Breadcrumb',
  setup() {
    const route = useRoute()
    const router = useRouter()
    const levelList = ref<Array<PartialRouteLocationMatched>>([])
    // 判断是不是Dashboard路由
    const isDashboard = (route?: PartialRouteLocationMatched) => {
      const name = route?.name
      if (!name) {
        return false
      }
      return (
        (name as string).trim().toLocaleLowerCase() ===
        'Dashboard'.toLocaleLowerCase()
      )
    }
    // 获取面包屑导航
    const getBreadcrumb = () => {
      // 过滤掉没有title的路由（不能作为面包屑）
      let matched = route.matched.filter(
        (item) => item.meta?.title
      ) as PartialRouteLocationMatched[]
      const first = matched[0]
      // 我们要把dashboard作为首页 始终固定在面包屑导航第一个 Dashboard/System/Menu Management
      // 如果第一个匹配到的路由记录不是dashboard 我们自己就把它放在记录数组的第一项
      if (!isDashboard(first)) {
        matched = ([
          {
            path: '/dashboard',
            meta: {
              title: 'Dashboard'
            }
          }
        ] as PartialRouteLocationMatched[]).concat(matched)
      }
      // route.meta.breadcrumb自定义属性 如果为false 匹配到时 将不会再面包屑导航显示该路由
      levelList.value = matched.filter(
        (item) => item.meta?.title && item.meta?.breadcrumb !== false
      )
    }
    onBeforeMount(() => {
      getBreadcrumb()
    })
    watch(
      () => route.path,
      () => {
        getBreadcrumb()
      }
    )
    // 主要针对动态路由/user/:id进行动态参数填充
    const pathCompile = (path: string) => {
      // 根据路径变编译成正则函数 并接收具体参数 比如根据正则/user/:id 帮你将:id替换成具体路径(/user/:id-->/user/10)
      const toPath = compile(path)
      const params = route.params
      return toPath(params)
    }
    // 点击面包屑导航可跳转
    const handleLink = (route: RouteLocationMatched) => {
      const { path, redirect } = route
      if (redirect) {
        router.push(redirect as RouteLocationRaw)
        return
      }
      router.push(pathCompile(path))
    }
    return {
      levelList,
      handleLink
    }
  }
})
</script>

<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
  display: inline-block;
  /* float: left; */
  line-height: 50px;
  font-size: 14px;
  margin-left: 8px;
}

.no-redirect {
  color: #97a8be;
  cursor: text;
}
</style>

<style lang="scss">
.breadcrumb-enter-active,
.breadcrumb-leave-active {
  transition: all 0.5s;
}

.breadcrumb-enter,
.breadcrumb-leave-active {
  opacity: 0;
  transform: translateX(20px);
}

.breadcrumb-leave-active {
  position: absolute;
}

.breadcrumb-move {
  transition: all 0.5s;
}
</style>
